
--[[
	**********************
	* SvFrame - thomasfn *
	**********************
	plugins.lua - Loads plugin functions
]]

svr.Plugins = svr.Plugins or {}

local plugins = {}

local basePlugin = {}
basePlugin.__index = basePlugin
basePlugin.Name = "baseplugin"
basePlugin.Title = "Base Plugin"
basePlugin.Author = "Unknown"

function basePlugin:Init()

end

function basePlugin:Hook( name, func )
	hooks.Add( name, "SvFrame_Plugin_" .. self.Name .. "_" .. name, function( ... ) return func( self, ... ) end )
	table.insert( self._hooks, name )
end

function basePlugin:RemoveHook( name )
	hooks.Remove( name, "SvFrame_Plugin_" .. self.Name .. "_" .. name )
	self._hooks[ name ] = nil
end

function basePlugin:IHook( name, func, def )
	svr.IHook( name, function( ... ) return func( self, ... ) end, def )
	self._ihooks[ name ] = func
end

function basePlugin:Command( name, func, validator )
	if (type( func ) == "function") then
		svr.AddCommand( name, function( ply, args )
			if (validator) then
				for _, flag in pairs( validator ) do
					if (not svr.PlayerHasFlag( ply, flag )) then
						ply:ChatPrint( colour.Red, "You do not have the ", colour.Teal, flag, colour.Red, " flag!" )
						return
					end
				end
			end
			func( self, ply, args )
		end )
	elseif (type( func ) == "table") then
		svr.AddCommand( name, func, validator )
	end
	table.insert( self._commands, name )
end

function basePlugin:Unload()
	for _, name in pairs( self._hooks ) do
		hooks.Remove( name, "SvFrame_Plugin_" .. self.Name .. "_" .. name )
	end
	for _, name in pairs( self._commands ) do
		svr.RemoveCommand( name )
	end
	for name, func in pairs( self._ihooks ) do
		svr.RemoveIHook( name, func )
	end
	self:OnUnload()
	self._hooks = {}
	self._commands = {}
	self.Loaded = false
end

function basePlugin:Reload()
	self:Unload()
	dofile( "lua/" .. self.Folder .. "/" .. self.Folder .. ".lua" )
	-- The plugin will load itself, we don't need to do it!
	--self:Load()
end

function basePlugin:Load()
	self:Init()
	self.Loaded = true
end

function basePlugin:OnUnload()
	
end

local pluginData = {}

function svr.ProcessPlugin( plugin_table )
	plugins[plugin_table.Name] = plugin_table
	
	if (not plugin_table.Folder) then
		svr.Warning( "Plugin '"..plugin_table.Title.."' is missing PLUGIN.Folder, /reload might not work!" )
		plugin_table.Folder = plugin_table.Name
	end
	
	setmetatable( plugin_table, basePlugin )
	--svr.Print("---pluginData-----------------")
	--svr.PrintTable(pluginData or {nothing = "here"});
	if (not pluginData[ plugin_table.Name ]) then
	--svr.Print("==============================")
		plugin_table:Load()
		svr.Print( "Plugin '"..plugin_table.Title.."' by '"..plugin_table.Author.."' installed and loaded." )
		svr.SavePluginData()
	else
	--svr.Print("------------------------------")
		svr.Print( "Plugin '"..plugin_table.Title.."' by '"..plugin_table.Author.."' installed." )
	end
end

function svr.LoadPluginData()
	local b, res = svr.FileToTable( "SvFrame/config/plugins" )
	if (not b) then
		svr.SavePluginData()
		svr.Print( "Failed to load plugin data! Will try again. (" .. res .. ")" )
		svr.LoadPluginData()
		return
	end
	pluginData = res
end

function svr.SavePluginData()
	local b, res = svr.TableToFile( "SvFrame/config/plugins", pluginData)
	if (not b) then
		svr.Print( "Failed to save plugin data! (" .. res .. ")" )
		return
	end
end

svr.LoadPluginData()

function svr.GetPlugins()
	return plugins
end

function svr.GetPlugin( name )
	return plugins[ name ]
end

svr.AddCommand( "plugins", function( ply, args )
	local tmp = {}
	for _, p in pairs( plugins ) do
		local col = COL_GREEN
		if (not p.Loaded) then col = COL_RED end
		tmp[ #tmp + 1 ] = col .. "^" .. p.Title .. COL_WHITE .. "^"
	end
	ply:ChatPrint( "Plugins installed: " .. table.concat( tmp, ", " ) )
end )

svr.AddCommand( "plugin", {
	["unload"] = function( ply, args )
		
		if (not svr.CheckArg( args, 1, "string" )) then
			return ply.Print( colour.White, "Syntax: /plugin unload <name>" )
		end
		
		local p = svr.GetPlugin( args[1] )
		if (not p) then
			return ply:ChatPrint( colour.Red, "No plugin is installed by that name!" )
		end
		if (not p.Loaded) then
			return ply:ChatPrint( colour.Teal, args[1], colour.Red, " is not loaded!" )
		end

		p:Unload()
		pluginData[ p.Name ] = true
		svr.SavePluginData()
		ply:ChatPrint( colour.White, "The plugin ", colour.Teal, args[1], colour.White, " was ", colour.Red, "unloaded", colour.White, "!" )
	end,
	
	load = function( ply, args )
		if (not svr.CheckArg( args, 1, "string" )) then
			return ply:ChatPrint( colour.White, "Syntax: /plugin unload <name>" )
		end
		local p = svr.GetPlugin( args[1] )
		if (not p) then return ply:ChatPrint( colour.Red, "No plugin is installed by that name!" ) end
		if (p.Loaded) then return ply:ChatPrint( colour.Teal, args[1], colour.Red, " is already loaded!" ) end
		p:Load()
		pluginData[ p.Name ] = false
		svr.SavePluginData()
		ply:ChatPrint( colour.White, "The plugin ", colour.Teal, args[1], colour.White, " was ", colour.Green, "loaded", colour.White, "!" )
	end,
	reload = function( ply, args )
		if (not svr.CheckArg( args, 1, "string" )) then return ply:ChatPrint( colour.White, "Syntax: /plugin unload <name>" ) end
		local p = svr.GetPlugin( args[1] )
		if (not p) then return ply:ChatPrint( colour.Red, "No plugin is installed by that name!" ) end
		p:Reload()
		ply:ChatPrint( colour.White, "The plugin ", colour.Teal, args[1], colour.White, " was ", colour.Green, "reloaded", colour.White, "!" )
	end
}, function( ply )
	if (ply.Op()) then return true end
	ply:ChatPrint( colour.Red, "You must be an op to use this command!" )
	return false
end )

for i=1, #svr.Plugins do
	local tbl = svr.Plugins[i]
	svr.ProcessPlugin( tbl )
end

svr.Plugins = setmetatable( {}, { __newindex = function( t, k, v ) svr.ProcessPlugin( v ) end } )
svr.SavePluginData()